/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */
package com.yami.shop.delivery.common.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.app.dto.DeliveryDto;
import com.yami.shop.bean.enums.DvyType;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.enums.SendType;
import com.yami.shop.bean.model.Delivery;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.OrderRefund;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.dao.OrderItemMapper;
import com.yami.shop.delivery.common.dao.DeliveryOrderMapper;
import com.yami.shop.delivery.common.model.DeliveryOrder;
import com.yami.shop.delivery.common.model.DeliveryOrderItem;
import com.yami.shop.delivery.common.param.DeliveryOrderItemParam;
import com.yami.shop.delivery.common.param.OrderItemParam;
import com.yami.shop.delivery.common.service.DeliveryOrderItemService;
import com.yami.shop.delivery.common.service.DeliveryOrderService;
import com.yami.shop.service.DeliveryService;
import com.yami.shop.service.NotifyTemplateService;
import com.yami.shop.service.OrderRefundService;
import com.yami.shop.service.OrderService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author lhd
 * @date 2020-04-22 15:46:05
 */
@Service
@AllArgsConstructor
public class DeliveryOrderServiceImpl extends ServiceImpl<DeliveryOrderMapper, DeliveryOrder> implements DeliveryOrderService {

    private final DeliveryOrderMapper deliveryOrderMapper;
    private final DeliveryOrderItemService deliveryOrderItemService;
    private final OrderService orderService;
    private final NotifyTemplateService notifyTemplateService;
    private final DeliveryService deliveryService;
    private final OrderRefundService orderRefundService;
    private final OrderItemMapper orderItemMapper;

    /**
     * 生成物流信息及保存物流与订单关联
     * @param deliveryOrderParam 物流信息
     * @param shopId 店铺id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDeliveriesInfo(DeliveryOrderItemParam deliveryOrderParam, Long shopId) {
        boolean isDelivery = true;
        List<OrderItem> selectOrderItems = deliveryOrderParam.getSelectOrderItems();
        selectOrderItems.forEach(i->i.setDvyType(deliveryOrderParam.getDeliveryType()));
        String orderNumber = deliveryOrderParam.getOrderNumber();
        Order order = orderService.getOrderAndOrderItemByOrderNumber(orderNumber);
        if(!Objects.equals(order.getShopId(),shopId)){
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        boolean isSend = Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.DELIVERY.value())
                || Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.NOT_DELIVERY.value()) ||
                Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.SAME_CITY.value());
        checkIsSend(deliveryOrderParam, selectOrderItems, order, isSend);
        orderItemMapper.updateByDeliveries(selectOrderItems);
        //判断是否发货完成
        List<OrderItem> orderItems;
        if (Objects.isNull(order.getRefundStatus())){
            orderItems = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, orderNumber));
        }else {
            orderItems = orderItemMapper.getListByOrderNumber(orderNumber);
            List<Long> orderItemIds = orderItems.stream().map(OrderItem::getOrderItemId).collect(Collectors.toList());
            orderItems.removeIf(orderItem -> Objects.nonNull(orderItem.getGiveawayOrderItemId()) && !orderItemIds.contains(orderItem.getGiveawayOrderItemId()));
        }
        // 有多个商品的订单，有退款记录的，并且有退款成功的单个商品，
        // 其余的商品都是发货完成的订单，改成发货状态
        // 在退款处理的时候将状态改为0即可
        for (OrderItem orderItem : orderItems) {
            if (orderItem.getStatus() != 0) {
                isDelivery = false;
                break;
            }
        }
        //修改为发货状态
        isDelivery(deliveryOrderParam, isDelivery, orderNumber, order);
    }

    private void isDelivery(DeliveryOrderItemParam deliveryOrderParam, boolean isDelivery, String orderNumber, Order order) {
        if(isDelivery){
            Date date = new Date();
            order.setStatus(OrderStatus.CONSIGNMENT.value());
            order.setUpdateTime(date);
            order.setDvyTime(date);
            //判断是无需物流还是快递发货
            order.setDvyType(deliveryOrderParam.getDeliveryType());
            // 如果是无需快递，则判断该订单是否包含有物流的项，若有物流则配送类型为快递配送，没有物流则不变
            if (Objects.equals(order.getDvyType(), DvyType.NOT_DELIVERY.value())) {
                List<DeliveryOrder> deliveryOrders = list(new LambdaQueryWrapper<DeliveryOrder>().eq(DeliveryOrder::getOrderNumber, orderNumber)
                        .eq(DeliveryOrder::getDeliveryType,DvyType.DELIVERY.value()));
                if (!CollectionUtils.isEmpty(deliveryOrders)){
                    order.setDvyType(1);
                }
            }
            orderService.updateById(order);
            String dvyName = "";
            if(Objects.equals(order.getDvyType(),DvyType.SAME_CITY.value())){
                dvyName = "店铺同城配送";
                order.setDvyFlowId("同城配送");
            }
            // 消息推送-发货提醒
            if(Objects.equals(order.getDvyType(), DvyType.DELIVERY.value())){
                Delivery delivery = deliveryService.getById(deliveryOrderParam.getDvyId());
                order.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
                dvyName = "";
                if(Objects.nonNull(delivery) && delivery.getDvyName() != null){
                    dvyName = delivery.getDvyName();
                }
            }
            if (Objects.equals(order.getDvyType(), DvyType.NOT_DELIVERY.value())){
                dvyName = "无需快递";
                order.setDvyFlowId("无需快递");
            }
            notifyTemplateService.sendNotifyOfDelivery(order,dvyName, SendType.DELIVERY);
        }
    }

    private void checkIsSend(DeliveryOrderItemParam deliveryOrderParam, List<OrderItem> selectOrderItems, Order order, boolean isSend) {
        if (isSend){
            //校验订单状态，发货数量及获取发货的总数
            int prodNumSum = checkDelivery(order, selectOrderItems);
            DeliveryOrder deliveryOrder = new DeliveryOrder();
            deliveryOrder.setOrderNumber(deliveryOrderParam.getOrderNumber());
            if (Objects.equals(deliveryOrderParam.getDeliveryType(),DvyType.DELIVERY.value())){
                deliveryOrder.setDvyId(deliveryOrderParam.getDvyId());
                deliveryOrder.setDvyFlowId(deliveryOrderParam.getDvyFlowId());
            }
            deliveryOrder.setCreateTime(new Date());
            deliveryOrder.setStatus(1);
            deliveryOrder.setReceiverMobile(order.getReceiverMobile());
            deliveryOrder.setProductNums(prodNumSum);
            deliveryOrder.setDeliveryType(deliveryOrderParam.getDeliveryType());
            //保存订单物流信息
            save(deliveryOrder);
            //保存需要添加的关联信息
            List<DeliveryOrderItem> addDeliveries = new ArrayList<>();
            for (OrderItem selectOrderItem : selectOrderItems) {
                DeliveryOrderItem deliveryOrderItem = new DeliveryOrderItem();
                deliveryOrderItem.setOrderItemId(selectOrderItem.getOrderItemId());
                deliveryOrderItem.setProdCount(selectOrderItem.getChangeNum());
                deliveryOrderItem.setOrderDeliveryId(deliveryOrder.getOrderDeliveryId());
                addDeliveries.add(deliveryOrderItem);
            }
            if(CollectionUtils.isNotEmpty(addDeliveries)){
                deliveryOrderItemService.saveBatch(addDeliveries);
            }
        }
    }


    /**
     * 修改物流信息
     * @param deliveryOrders 物流修改的信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderDeliveries(List<DeliveryOrder> deliveryOrders) {
        updateBatchById(deliveryOrders);
    }

    @Override
    public List<DeliveryOrder> getAndDeliveryItemInfo(String orderNumber,Integer lang) {
        List<DeliveryOrder> deliveryOrders = deliveryOrderMapper.getAndDeliveryItemInfo(orderNumber, null, lang);
        if (CollUtil.isEmpty(deliveryOrders)) {
            return new ArrayList<>();
        }
        // 查询物流详情信息
        // 物流公司名称、官网、订单号、物流详情信息
        DeliveryOrder deliveryOrder = deliveryOrders.get(0);
        if (Objects.nonNull(deliveryOrder.getDvyId())){
            // 查询交易单
            DeliveryDto deliveryDto = getDelivery(deliveryOrder);
            deliveryOrder.setDeliveryDto(deliveryDto);
            if(Objects.nonNull(deliveryOrder.getDeliveryDto()) && CollectionUtils.isNotEmpty(deliveryOrder.getDeliveryDto().getTraces())){
                Collections.reverse(deliveryOrder.getDeliveryDto().getTraces());
            }
        }
        for (DeliveryOrder order : deliveryOrders) {
            Map<Long, List<OrderItemParam>> itemMap = order.getOrderItems().stream().collect(Collectors.groupingBy(OrderItemParam::getSkuId));
            List<OrderItemParam> orderItemParams = new ArrayList<>();
            for (Long skuId : itemMap.keySet()) {
                int sum = itemMap.get(skuId).stream().mapToInt(OrderItemParam::getProdCount).sum();
                OrderItemParam orderItemParam = itemMap.get(skuId).get(0);
                orderItemParam.setProdCount(sum);
                orderItemParams.add(orderItemParam);
            }
            order.setOrderItems(orderItemParams);
        }
        return deliveryOrders;
    }

    @Override
    public List<DeliveryOrder> listDetailDelivery(String orderNumber) {
        return deliveryOrderMapper.listDetailDelivery(orderNumber, I18nMessage.getDbLang());
    }

    @Override
    public DeliveryOrder deliveryOrderItemInfo(Long orderDeliveryId, Integer lang) {
        List<DeliveryOrder> deliveryOrders = deliveryOrderMapper.getAndDeliveryItemInfo(null, orderDeliveryId, lang);
        if (CollUtil.isEmpty(deliveryOrders)) {
            return new DeliveryOrder();
        }
        DeliveryOrder deliveryOrder = deliveryOrders.get(0);
        if (Objects.nonNull(deliveryOrder) && Objects.nonNull(deliveryOrder.getDvyId())){
            // 查询交易单
            DeliveryDto deliveryDto = getDelivery(deliveryOrder);
            deliveryOrder.setDeliveryDto(deliveryDto);
            if(Objects.nonNull(deliveryOrder.getDeliveryDto()) && CollectionUtils.isNotEmpty(deliveryOrder.getDeliveryDto().getTraces())){
                Collections.reverse(deliveryOrder.getDeliveryDto().getTraces());
            }
        }
        // 处理下相同的sku信息集合
        Map<Long, List<OrderItemParam>> itemMap = deliveryOrder.getOrderItems().stream().collect(Collectors.groupingBy(OrderItemParam::getSkuId));
        List<OrderItemParam> orderItemParams = new ArrayList<>();
        for (Long skuId : itemMap.keySet()) {
            int sum = itemMap.get(skuId).stream().mapToInt(OrderItemParam::getProdCount).sum();
            OrderItemParam orderItemParam = itemMap.get(skuId).get(0);
            orderItemParam.setProdCount(sum);
            orderItemParams.add(orderItemParam);
        }
        deliveryOrder.setOrderItems(orderItemParams);
        return deliveryOrder;
    }

    private DeliveryDto getDelivery(DeliveryOrder deliveryOrder){
        DeliveryDto deliveryDto;
        try {
            Delivery delivery = deliveryService.getById(deliveryOrder.getDvyId());
            // 解析的物流详情明细
            deliveryDto = deliveryService.query(delivery.getDvyId(), deliveryOrder.getDvyFlowId(), deliveryOrder.getReceiverMobile());
            deliveryDto.setCompanyHomeUrl(delivery.getCompanyHomeUrl());
            deliveryDto.setCompanyName(delivery.getDvyName());
            deliveryDto.setDvyFlowId(deliveryOrder.getDvyFlowId());
        } catch (Exception e) {
            log.error("物流查询错误：", e);
            // 查询出错
            throw new YamiShopBindException("yami.query.error");
        }
        return deliveryDto;
    }

    /**
     * 校验可发货数量并返回总数
     * @param order 订单信息
     * @param selectOrderItems 选择发货的订单项
     */
    private int checkDelivery(Order order, List<OrderItem> selectOrderItems) {
        if (!Objects.equals(order.getStatus(), OrderStatus.PADYED.value()) && Objects.equals(order.getDvyType(), DvyType.STATION.value())) {
            // 订单不处于待入库状态，无法进行入库
            throw new YamiShopBindException("yami.order.status.no.right");
        } else if (!Objects.equals(order.getStatus(), OrderStatus.PADYED.value())) {
            // 订单不处于待发货状态，无法进行发货
            throw new YamiShopBindException("yami.order.delivery.no.right");
        }
        List<OrderRefund> orderRefunds = orderRefundService.getProcessingOrderRefundByOrderId(order.getOrderId());
        // 移除退款成功的退款记录
        orderRefunds.removeIf(orderRefund -> orderRefund.getReturnMoneySts() == 5);
        if (CollectionUtil.isNotEmpty(orderRefunds)) {
            // 该订单有退款信息正在处理当中，请处理完毕之后再进行发货的操作!
            throw new YamiShopBindException("yami.order.delivery.refund.error");
        }
        Map<Long, OrderItem> itemMap = order.getOrderItems().stream().collect(Collectors.toMap(OrderItem::getOrderItemId, orderItem -> orderItem));
        //获取发货总数
        int prodNumSum = 0;
        for (OrderItem selectOrderItem : selectOrderItems) {
            prodNumSum += selectOrderItem.getChangeNum();
            if(!itemMap.containsKey(selectOrderItem.getOrderItemId())){
                // 订单不存在
                throw new YamiShopBindException("yami.order.no.exist");
            }
            OrderItem orderItemDb = itemMap.get(selectOrderItem.getOrderItemId());
            // 这里把数据库查询到的数量放进去，以免前端传了错误的数量
            selectOrderItem.setProdCount(Objects.equals(orderItemDb.getStatus(),-1) ? orderItemDb.getProdCount() : orderItemDb.getStatus());
            if(!Objects.equals(orderItemDb.getStatus(),-1) && orderItemDb.getStatus() < selectOrderItem.getChangeNum()){
                // 订单发货数量不足，请刷新后再试
                throw new YamiShopBindException("yami.order.delivery.num.check");
            }
        }
        return prodNumSum;
    }
}
